        TITL DAI FIRMWARE 3E000-3E1F5  V1.0  Rev.1
        ORG   :E000
*
*
*
*   ===========================
*** ENCODING / UTILITY PACKAGES ***
*   ===========================
*
* Called by RST 1; DATA XX. XX indicates the
* offset of E000 for the different entrypoints.
*
* Contains also the key encoding routines and the
* Heap organisation routines.
*
***************
* ENTRYPOINTS *
***************
*
ELINE   JMP   :E024     Encode a BASIC line
ELN     JMP   :E72A     Encode a linenr
ETCON   JMP   :E145     Encode a constant
USTART  JMP   :EA74     Start Utility package
DBOOT   JMP   :EF90     Disc bootstrap
MHREQ   JMP   :E99C     Heap request
MINKEY  JMP   :E93F     Encode a key input
L3E394  JMP   :E935     Get inputs from keyb
 REM or DINC
*
*   ================
*** ENCODING PACKAGE ***
*   ================
*
* Generally in the encoding routines, HL points to
* the first free location in the EBUF. C points to
* the input text line.
*
***********************
* UPDATE EBUF POINTER *
***********************
*
* Increments the input pointer and checks if the
* encoded input buffer (EBUF) is full.
*
* Entry: HL: input pointer EBUF.
* Exit:  HL: updated pointer.
*        Other registers preserved.
*
INXCH   INX   H         Incr pointer
        PUSH  PSW
        MOV   A,L       Get lobyte in A
        CPI   :BE       Max value reached?
        MVI   A,:1A     Buffer full ?
        JNC   :D9F5     Then run error 'LINE TOO
 REM COMPLEX'
        POP   PSW
        RET
*
**************************
* ENCODE A BASIC COMMAND *
**************************
*
* Looks for a match between input on line and the
* BASIC command table #CBBF. Error exit 'COMMAND
* INVALID' if the 2 high order bits of the code in
* the table don't match the mask in D. Else the
* code (#80 + low order 6 bits from code in table)
* are stored in EBUF.
*
* Entry: HL: 1st free position in EBUF.
*        D : Mask for direct command (#80) or
*            program input (#40).
*        C : Position on current line.
* Exit:  HL: Updated.
*        C : Points to 1st not used input in line.
*        E : Code just stored.
*        BD preserved, AF corrupted.
*        Exit with jump to address found in table.
*        #E04F is on stack as next returnaddress,
*        entry DE is next on stack.
*
L3E2    PUSH  D
        PUSH  H
        LXI   H,:E04F   Returnaddr after finishing
 REM encoding
        XTHL            Save it on stack
        PUSH  H         Save HL again
        MVI   E,:02     Addit. offset for finding
 REM instruction in table
        LXI   H,:CBBF   Startaddr table with strings
 REM Basiccommands
        PUSH  D
        CALL  :CA34     Find instr in table
        POP   D         Get mask for direct/program
        MOV   A,M       Get instr code from table
        ANI   :C0       ) Check if it
        ANA   D         ) is a valid command
        MVI   A,:18     If not: Run error
        JZ    :D9F5     'COMMAND INVALID'
        MOV   A,M       Get instr code from table
        INX   H
        ANI   :3F       ) Make it a token
        ORI   :80       )
        MOV   E,A       Store token in E
        MOV   A,M       )
        INX   H         ) Get addr of encoding
        MOV   H,M       ) instruction in HL
        MOV   L,A       )
        XTHL            and save it on stack
        MOV   M,E       Store token in EBUF
        CALL  :E018     Update EBUF pointer
        RET             Go to encoding instruction
 REM return afterwards to E04F
*
* End of encoding of an input line (after running
* the command specific processing).
* Checks if character after BASIC command is CR or
* ';'.
*
* Entry: C : points to position on current line.
*        On stack: Original DE.
*
L3E3    POP   D         Get type of command in D
        CALL  :DDD2     Get char from line, neglect
 REM tab + space
        INR   C         Pntr to next char
        CPI   :3A       ':' ?
        JZ    :E024     Then encode next instr
        CPI   :0D       'CR' ?
        JNZ   :DA0B     Run 'SYNTAX ERROR' if not
        RET
*
******************************
* ENCODE 'FOR - TO - (STEP)' *
******************************
*
* Valid for all specific encoding routines:
* HL points to 1st free EBUF location.
*
EFOR    CALL  :E0FE     Encode 'LET'
        CPI   :20       String type ?
        JZ    :DA1A     Then run error 'TYPE
 REM MISMATCH'
        CPI   :10       INT type ?
        LXI   D,:E088   Addr 'TO' table
        JMP   :E09A     Get addr encoding instr and
 REM go to it
 REM
* Encode 'TO':
 REM
L3E5    CZ    :E36D     Encode a INT expr
        CNZ   :E376     Encode a FPT expr
        LXI   D,:E090   Addr 'STEP' table
        JMP   :E09A     Get addr encoding instr and
 REM go to it
 REM
* Encode 'STEP':
 REM
L3E6    CZ    :E36D     Encode a INT expr
        CNZ   :E376     Encode a FPT expr
        RET
 REM
* End encoding:
 REM
L3E363  MVI   M,:FF     FF in EBUF as separator
        CALL  :E018     Update EBUF pointer
        RET
 REM
* Table:
 REM
L3E395  DATA  :02
        DATA  :54       T
        DATA  :4F       O
        DBL   :E06F     Addr encode 'TO'
*
        DATA  :00       'TO' not found:
        DBL   :DA0B     Run 'SYNTAX ERROR'
*
L3E396  DATA  :04
        DATA  :53       S
        DATA  :54       T
        DATA  :45       E
        DATA  :50       P
        DBL   :E07B     Addr encode 'STEP'
*
        DATA  :00       'STEP' not found:
        DBL   :E082     End command
*
*************************************************
* GET ADDRESS ENCODING INSTRUCTION AND GO TO IT *
*************************************************
*
* Entry: DE : Points to table of format:
*             < length name / name / jumpaddr > or
*             < 00 / jumpaddr >.
*        C  : Points to input.
* Exit:  C  : Updated.
*        AFBHL preserved. D=0, E=1.
*
L3E7    PUSH  H
        PUSH  PSW
        XCHG            Addr table in HL
        MVI   E,:01
        CALL  :CA34     Find instruction in table.
 REM On exit, HL points to addr
 REM of encoding routine
        MOV   A,M       )
        INX   H         ) Get addr encoding instr
        MOV   H,M       ) in HL
        MOV   L,A       )
        POP   PSW
        XTHL            Addr encoding instr on stack
        RET             Go to it
*
***************************************
* ENCODE 'NEXT' AND 'NEXT <VARIABLE>' *
***************************************
*
ENEXT   CALL  :E859     Next char ':' or 'CR' ?
        RZ              Then ready
 REM
* If NEXT <variable>:
 REM
        DCX   H
        INR   M         Token +1 (#AC)
        INX   H
        CALL  :E5BC     Encode variable or array ref
        LDA   :0136     Get type latest expression
        CPI   :20       String type ?
        JZ    :DA1A     Then run error 'TYPE
 REM MISMATCH'
        RET
*
**************************************
* ENCODE 'IF - THEN' AND 'IF - GOTO' *
**************************************
*
EIF     PUSH  H
        PUSH  D
        CALL  :E39C     Encode boolean expr (type
 REM #30)
        LXI   D,:E0ED   Addr 'THEN' table
        JMP   :E09A     Get addr encoding instr
 REM and go to it
 REM
* Encode 'THEN':
 REM
L3E10   CALL  :E731     Read a linenr into EBUF
        POP   D
        JNC   :E0D4     Jump if no linenr given
 REM
* If linenr:
 REM
        XTHL
        DCX   H
        INR   M
        INR   M         Token +2 (#A8)
        POP   H
        RET
 REM
* If statement:
 REM
L3E11   POP   PSW
        PUSH  H         Preserve EBUF pntr
        CALL  :E018     Update EBUF pointer
        CALL  :E024     Encode BASIC command
        MOV   A,L       Lobyte new EBUF pntr in A
        XTHL            Old EBUF pntr in HL
        SUB   L
        DCR   A
        MOV   M,A       Length string in EBUF entry
        POP   H
        DCR   C
        RET
 REM
* Encode 'GOTO':
 REM
L3E12   POP   PSW
        XTHL
        DCX   H
        INR   M         Token +1 (#A7)
        POP   H
        CALL  :E72A     Get linenr
        RET
 REM
* Table:
 REM
L3E397  DATA  :04
        DATA  :54       T
        DATA  :48       H
        DATA  :45       E
        DATA  :4E       N
        DBL   :E0C7     Addr encode 'THEN'
*
        DATA  :04
        DATA  :47       G
        DATA  :4F       O
        DATA  :54       T
        DATA  :4F       O
        DBL   :E0E4     Addr encode 'GOTO'
*
        DATA  :00       If no 'THEN' or 'GOTO' found
        DBL   :DA0B     Run 'SYNTAX ERROR'
*
****************
* ENCODE 'LET' *
****************
*
* Encodes a variable or array with arguments. Then
* finds '=' in input (error if not). Then encodes
* an expression, depending on variable type (error
* if type non-existing).
*
* Exit: DE: Offset of left-side variable.
*       A and B: Left-side type.
*       C, HL updated. F corrupted.
*
ELET    CALL  :E5BC     Encode var or array ref
        CALL  :E867     Check next char is '='
        DATA  :3D
        LDA   :0136     Get type latest expression
        CPI   :00       FPT ?
        JZ    :E376     Then encode FPT expr
        CPI   :10       INT ?
        JZ    :E36D     Then encode INT expr
        JMP   :E3A1     Else encode STR expr
*
***************************************
* ENCODE 'INPUT' AND 'INPUT <STRING>' *
***************************************
*
EINPUT  CALL  :DDD2     Get char from line, neglect
 REM tab + space
        CPI   :22       '"' ?
        JNZ   :E127     Encode 'READ' if no string
 REM in INPUT statement
 REM
* If 'INPUT <string>':
 REM
        DCX   H
        INR   M         Token +1 (#A1)
        INX   H
        CALL  :E3A1     Encode STR expr
        CALL  :E867     Check if next char is ';'
        DATA  :3B
 REM Into EREAD
*
*****************
* ENCODE 'READ' *
*****************
*
* From L3E16 used by several routines, with another
* address in LXI D, ...., pointing to various kinds
* of encoding/get routines.
*
EREAD   LXI   D,:E5BC   Addr routine encode variable
 REM or array reference
*
L3E16   PUSH  H
        MVI   M,:00     00 into EBUF (count)
        CALL  :E018     Update EBUF pointer
L3E17   PUSH  D
        CALL  :E164     Go to encoding routine
 REM
* Return here after encoding:
 REM
        POP   D
        XTHL
        INR   M         Count in EBUF +1
        XTHL
        CALL  :DDD2     Get char from line, neglect
 REM tab + space
        INR   C         Points to next char on line
        CPI   :2C       ',' ?
        JZ    :E130     Again if more items
        DCR   C         Correct line pointer
        INX   SP
        INX   SP        SP to returnaddr
        RET
*
**************************************
* ENCODE A NUMBER OR STRING CONSTANT *
**************************************
*
* Entry: A: Type.
*
L3E18   PUSH  PSW       Preserve type
        ORA   A
        JZ    :E15E     Jump if FPT type
        CPI   :10
        JZ    :E888     Jump if INT type
 REM
* If STR type:
 REM
        CALL  :DDD2     Get char from line, neglect
 REM tab + space
        CPI   :22       '"' (quoted string) ?
        PUSH  PSW
        CZ    :E880     Then store quoted string
 REM in EBUF
        POP   PSW
        CNZ   :E6A6     Else store unquoted string
 REM in EBUF
L3E19   POP   PSW
        RET
 REM
* If FPT type:
 REM
L3E20   CALL  :E501     Encode FPT nr into EBUF
        JMP   :E893     Quit with evt 'SYNTAX ERROR'
*
*************************
* part of EREAD (3E12A) *
*************************
*
L3E21   PUSH  D         Addr encoding routine on
 REM stack
        RET             Go to it
*
****************
* ENCODE 'DIM' *
****************
*
EDIM    LXI   D,:E16C   Addr routine 'encoding array
 REM reference'
        JMP   :E12A     Continu encoding
*
*****************************
* ENCODE AN ARRAY REFERENCE *
*****************************
*
L3E23   CALL  :E5BC     Encode var or array ref
        MOV   A,B       Type in A
        ANI   :40       Array type ?
        JZ    :DA29     Run 'SUBSCRIPT ERROR' if not
        RET
*
***************************************
* ENCODE 'ON - GOTO' AND 'ON - GOSUB' *
***************************************
*
EON     PUSH  H
        CALL  :E36D     Encode INT expr
        LXI   D,:E18D   Addr table
        JMP   :E09A     Get addr encoding instr
 REM and go to it
 REM
* Encode linenr in GOSUB (L3E25) and GOTO (L3E411):
 REM
L3E25   XTHL
        DCX   H
        INR   M         Token +1 (#AF)
        INX   H
        XTHL
L3E411  XTHL
        POP   H
        LXI   D,:E72A   Addr routine 'get linenr'
        JMP   :E12A     Continu encoding
 REM
* Table:
 REM
L3E399  DATA  :04
        DATA  :47       G
        DATA  :4F       O
        DATA  :54       T
        DATA  :4F       O
        DBL   :E185     Addr encode 'GOTO'
*
        DATA  :05
        DATA  :47       G
        DATA  :4F       O
        DATA  :53       S
        DATA  :55       U
        DATA  :42       B
        DBL   :E180     Addr encode 'GOSUB'
*
        DATA  :00       If no GOTO or GOSUB found:
        DBL   :DA0B     Run 'SYNTAX ERROR'
*
******************
* ENCODE 'PRINT' *
******************
*
EPRINT  PUSH  H
        MVI   M,:00     00 into EBUF (init length)
        CALL  :E859     Next char ':' or 'CR' ?
        JZ    :E1CB     Then ready
 REM
* If statement after PRINT:
 REM
L3E27   CALL  :E018     Update EBUF pointer
        XTHL
        INR   M         Length +1
        XTHL
        CALL  :E3B2     Encode non-boolean expr
 REM preceeded by its type
        MVI   M,:FF     FF into EBUF
        CALL  :E859     Next char ':' or 'CR' ?
        JZ    :E1CB     Then ready
 REM
* If more statements:
 REM
        MOV   M,A       Char into EBUF
        CPI   :2C       ',' ?
        JZ    :E1C4     Then continu
        CPI   :3B       ';' ?
        JNZ   :DA0B     Run 'SYNTAX ERROR' if not
L3E28   INR   C         Update line pntr
        CALL  :E859     Next char ':' or 'CR' ?
        JNZ   :E1A8     Continu if not
*
L3E29   XTHL
        POP   H
        CALL  :E018     Update EBUF pointer
        RET
*
*****************
* ENCODE 'MODE' *
*****************
*
EMODE   MVI   D,:FF     Default mode 0
        CALL  :DDD2     Get char from line, neglect
 REM tab + space
        INR   C         Points to next char
        SUI   :30
        JZ    :E1F1     If char is '0': FF in EBUF
        JC    :DA0B     Run 'SYNTAX ERROR' if not
 REM number or printable char
        CPI   :07       Between 0 and 7?
        JNC   :DA15     Run error 'NUMBER OUT OF
 REM RANGE' if not
        DCR   A         )
        ADD   A         ) Calc code for mode
        MOV   D,A       in D
        CALL  :DDE0     Get next char from line
        CPI   :41       'A' ?
        JNZ   :E1F1     Jump if not
        INR   C         Points to next char
        INR   D         Set D for A-mode
L3E31   MOV   M,D       Mode code in EBUF
        CALL  :E018     Update EBUF pointer
        RET
*
*
*
        END
